/*
 * Copyright (C) by Argonne National Laboratory
 *     See COPYRIGHT in top-level directory
 */

/**
 * \file ad_gpfs_flush.c
 * \brief Scalable flush for GPFS
 */

#include "ad_gpfs.h"

void ADIOI_GPFS_Flush(ADIO_File fd, int *error_code)
{
    int err = 0;
    static char myname[] = "ADIOI_GPFS_FLUSH";

    int rank;

    MPI_Comm_rank(fd->comm, &rank);

    /* the old logic about who is an fsync aggregator and who is not fell down
     * when deferred open was enabled.  Instead, make this look more like
     * ad_pvfs2_flush.  If one day the I/O aggregators have something they need
     * to flush, we can consult the 'fd->hints->ranklist[]' array.  For now, a
     * flush from one process should suffice */

    /* ensure all other processes are done writing. On many platforms MPI_Reduce
     * is fastest because it has the lightest constraints. On Blue Gene, BARRIER
     * is optimized  */
    MPI_Barrier(fd->comm);

    if (rank == fd->hints->ranklist[0]) {
        err = fsync(fd->fd_sys);
        DBG_FPRINTF(stderr, "aggregation:fsync %s, err=%#X, errno=%#X\n", fd->filename, err, errno);
        /* We want errno, not the return code if it failed */
        if (err == -1)
            err = errno;
        else
            err = 0;
    }
    MPI_Bcast(&err, 1, MPI_UNSIGNED, fd->hints->ranklist[0], fd->comm);
    DBGV_FPRINTF(stderr, "aggregation result:fsync %s, errno %#X,\n", fd->filename, err);

    if (err) {  /* if it's non-zero, it must be an errno */
        errno = err;
        err = -1;
    }

    /* --BEGIN ERROR HANDLING-- */
    if (err == -1) {
        *error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
                                           myname, __LINE__, MPI_ERR_IO,
                                           "**io", "**io %s", strerror(errno));
        DBGT_FPRINTF(stderr, "fsync %s, err=%#X, errno=%#X\n", fd->filename, err, errno);
        return;
    }
    /* --END ERROR HANDLING-- */

    *error_code = MPI_SUCCESS;
}
